<template>
	<div class="color-hue-slider" :class="{ 'is-vertical': vertical }">
		<div ref="bar" class="color-hue-slider__bar" @click="handleClick"></div>
		<div
			ref="thumb"
			class="color-hue-slider__thumb"
			:style="{
				left: thumbLeft + 'px',
				top: thumbTop + 'px',
			}"
		></div>
	</div>
</template>

<script setup lang="ts">
import draggable from '../util/draggable';
import type { Nullable } from '../color-picker';
import { HueSliderProps } from '../color-picker';

const props = defineProps(HueSliderProps);
const instance = getCurrentInstance();

const thumb = ref<Nullable<HTMLElement>>(null); //管理thumb
const bar = ref<Nullable<HTMLElement>>(null); //管理bar
const thumbLeft = ref(0);
const thumbTop = ref(0);

/**
 * 计算hueValue
 */
let hueValue = computed(() => props.color.get('hue'));

/**
 * 监听hueValue值
 */
watch(
	() => hueValue.value,
	() => {
		update();
	}
);

/**
 * handleClick点击事件
 * @param event
 */
const handleClick = (event: Event) => {
	const target = event.target;
	if (target !== thumb.value) {
		handleDrag(event);
	}
};

/**
 * handleDrag拖拽事件
 * @param event
 */
const handleDrag = (event: any) => {
	const ele = instance?.vnode.el as HTMLElement;
	const rect = ele.getBoundingClientRect();
	let hue;
	if (!props.vertical) {
		let left = event.clientX - rect.left;
		left = Math.min(
			left,
			rect.width - (thumb.value as HTMLElement).offsetWidth / 2
		);
		left = Math.max((thumb.value as HTMLElement).offsetWidth / 2, left);

		hue = Math.round(
			((left - (thumb.value as HTMLElement).offsetWidth / 2) /
				(rect.width - (thumb.value as HTMLElement).offsetWidth)) *
				360
		);
	} else {
		let top = event.clientY - rect.top;

		top = Math.min(
			top,
			rect.height - (thumb.value as HTMLElement).offsetHeight / 2
		);
		top = Math.max((thumb.value as HTMLElement).offsetHeight / 2, top);
		hue = Math.round(
			((top - (thumb.value as HTMLElement).offsetHeight / 2) /
				(rect.height - (thumb.value as HTMLElement).offsetHeight)) *
				360
		);
	}
	props.color.set('hue', hue);
};

/**
 * 获取Thumb左侧
 */
const getThumbLeft = (): number => {
	const ele = instance?.vnode.el as HTMLElement;

	if (props.vertical) return 0;
	const hue = props.color.get('hue');

	if (!ele) return 0;
	return Math.round(
		(hue * (ele.offsetWidth - (thumb.value as HTMLElement).offsetWidth / 2)) /
			360
	);
};

/**
 * 获取Thumb顶部
 */
const getThumbTop = (): number => {
	const ele = instance?.vnode.el as HTMLElement;
	if (!props.vertical) return 0;
	const hue = props.color.get('hue');

	if (!ele) return 0;
	return Math.round(
		(hue * (ele.offsetHeight - (thumb.value as HTMLElement).offsetHeight / 2)) /
			360
	);
};

/**
 * update更新事件
 */
const update = () => {
	thumbLeft.value = getThumbLeft();
	thumbTop.value = getThumbTop();
};
defineExpose({ update });
onMounted(() => {
	const dragConfig = {
		drag: (event: any) => {
			handleDrag(event);
		},
		end: (event: any) => {
			handleDrag(event);
		},
	};
	draggable(bar.value as HTMLElement, dragConfig);
	draggable(thumb.value as HTMLElement, dragConfig);
	update();
});
</script>
